package annotations.el;

import annotations.util.*;

/**
 * A {@link BoundLocation} holds location information for a bound of a type
 * parameter of a class or method: parameter index and bound index.
 */
public final /*@Unmodifiable*/ class BoundLocation {
    /**
     * The index of the parameter to which the bound applies among all
     * type parameters of the class or method.
     */
    public final int paramIndex;

    /**
     * The index of the bound among all bounds on the type parameter.
     */
    public final int boundIndex;

    /**
     * Constructs a new {@link BoundLocation}; the arguments are assigned to
     * the fields of the same names.
     */
    public BoundLocation(int paramIndex, int boundIndex) {
        this.paramIndex = paramIndex;
        this.boundIndex = boundIndex;
    }

    /**
     * Returns whether this {@link BoundLocation} equals <code>o</code>; a
     * slightly faster variant of {@link #equals(Object)} for when the argument
     * is statically known to be another nonnull {@link BoundLocation}.
     */
    public boolean equals(/*@NonNull*/ BoundLocation l) {
        return paramIndex == l.paramIndex && boundIndex == l.boundIndex;
    }

    /**
     * This {@link BoundLocation} equals <code>o</code> if and only if
     * <code>o</code> is another nonnull {@link BoundLocation} and
     * <code>this</code> and <code>o</code> have equal {@link #paramIndex}
     * and {@link #boundIndex}.
     */
    @Override
    public boolean equals(/*@ReadOnly*/ Object o) {
        return o instanceof BoundLocation
                && equals((/*@NonNull*/ BoundLocation) o);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() /*@ReadOnly*/ {
        /*@NonNull*/ Hasher h = new Hasher();
        h.mash(paramIndex);
        h.mash(boundIndex);
        return h.hash;
    }
}
